﻿#pragma once

enum Colour
{
	red,
	black,
};

template<class K, class V>
struct RBTreeNode
{
	pair<K, V> _kv;
	RBTreeNode<K, V>* _left;
	RBTreeNode<K, V>* _right;
	RBTreeNode<K, V>* _parent;
	Colour _col;

	RBTreeNode(const pair<K, V>& kv)
		:_kv(kv)
		, _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _col(red)
	{}
};

template<class K, class V>
class RBTree
{
	typedef RBTreeNode<K, V> Node;
public:
	bool Insert(const pair<K, V>& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_col = black;
			return true;
		}

		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_kv.first < kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_kv.first > kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}
		}

		cur = new Node(kv);
		cur->_col = red;
		if (parent->_kv.first < kv.first)
		{
			parent->_right = cur;
			cur->_parent = parent;
		}
		else
		{
			parent->_left = cur;
			cur->_parent = parent;
		}

		while (parent && parent->_col == red) // 如果父亲是黑色，直接插入就没问题，所以要对父亲是红色的情况处理
		{
			Node* grandfater = parent->_parent;//记录祖父
			if (parent == grandfater->_left) //如果他是祖父的左孩子
			{
				Node* uncle = grandfater->_right; //那么叔叔就是祖父的右孩子
				// 情况一  uncle存在且为红
				if (uncle && uncle->_col == red)
				{
					parent->_col = uncle->_col = black; //父亲和叔叔一起变黑
					grandfater->_col = red; //祖父变红

					cur = grandfater; //此时相当于要对祖父调整（向上调整），把cur（要调整的节点）赋值成祖父
					parent = cur->_parent; //父亲节点相应改变
				}
				else //叔叔不存在/叔叔是黑（情况二/三），此时p已经是祖父的左孩子（大前提的if）
				{
					if (cur == parent->_left)  //cur是左孩子 ，此时是情形二
					{
						RotateR(grandfater); //对祖父右旋
						parent->_col = black; //此时的p是子树的根，设为黑
						grandfater->_col = red;//祖父变成p的孩子，和cur一样设置成红色
					}
					else //cur是右孩子
					{
						// 情况三，也就是构成折线
						RotateL(parent); //cur是p的右孩子，左旋p，然后变成情况二的cur是p左孩子
						RotateR(grandfater); //在情况二且cur是p左孩子时，需要右旋祖父
						cur->_col = black; //操作和情形二&&cur是左孩子的一样
						grandfater->_col = red;
					}

					break; //这可子树已经没问题，但是此时应该向上调整
				}
			}
			else //p是祖父的右孩子，和上面基本上没区别
			{
				Node* uncle = grandfater->_left; //那么叔叔就是祖父的左孩子
				// 情况一  uncle存在且为红
				if (uncle && uncle->_col == red)
				{
					parent->_col = uncle->_col = black; //父亲和叔叔一起变黑
					grandfater->_col = red; //祖父变红

					cur = grandfater; //此时相当于要对祖父调整（向上调整），把cur（要调整的节点）赋值成祖父
					parent = cur->_parent; //父亲节点相应改变
				}
				else //叔叔不存在/叔叔是黑（情况二/三），此时p已经是祖父的右孩子（大前提的if）
				{
					if (cur == parent->_right)  //cur是右孩子 ，此时是情形二
					{
						RotateL(grandfater); //对祖父左旋
						parent->_col = black; //此时的p是子树的根，设为黑
						grandfater->_col = red;//祖父变成p的孩子，和cur一样设置成红色
					}
					else //cur是左孩子
					{
						// 情况三，也就是构成折线
						RotateR(parent); //cur是p的左孩子，右旋p，然后变成情况二的cur是p右孩子
						RotateL(grandfater); //在情况二且cur是p右孩子时，需要左旋祖父
						cur->_col = black; //操作和情形二&&cur是右孩子的一样
						grandfater->_col = red;
					}

					break; //这可子树已经没问题，但是此时应该向上调整
				}

			}
		}

		_root->_col = black; //把根节点设为黑色

		return true;
	}


	//下面实现旋转，其实和AVL没区别，只是没有bf因子
	void RotateL(Node* parent)
	{
		Node* subR = parent->_right;
		Node* subRL = subR->_left;

		parent->_right = subRL;
		if (subRL)
			subRL->_parent = parent;

		Node* ppNode = parent->_parent;
		subR->_left = parent;
		parent->_parent = subR;


		if (ppNode == nullptr)
		{
			_root = subR;
			_root->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subR;
			}
			else
			{
				ppNode->_right = subR;
			}

			subR->_parent = ppNode;
		}

	}

	void RotateR(Node* parent)
	{
		Node* subL = parent->_left;
		Node* subLR = subL->_right;

		parent->_left = subLR;
		if (subLR)
		{
			subLR->_parent = parent;
		}

		Node* ppNode = parent->_parent;
		subL->_right = parent;
		parent->_parent = subL;

		//if (_root == parent)
		if (ppNode == nullptr)
		{
			_root = subL;
			_root->_parent = nullptr;
		}
		else
		{
			if (ppNode->_left == parent)
			{
				ppNode->_left = subL;
			}
			else
			{
				ppNode->_right = subL;
			}

			subL->_parent = ppNode;
		}

	}

private:
	Node* _root = nullptr;
};